<template>
  <vxe-modal
    ref="modalRef"
    v-bind="getBindValue"
    v-model="openRef"
    :before-hide-method="beforeHideFn"
    @show="showEvent"
    @hide="hideEvent"
    @confirm="confirmEvent"
    @cancel="cancelEvent"
    @close="closeEvent"
    @zoom="zoomEvent"
  >
    <template #title v-if="!$slots.title">
      <ModalHeader
        :helpMessage="getProps.helpMessage"
        :title="getMergeProps.title"
        @dblclick="titleDbClickEvent"
      />
    </template>

    <template #footer v-if="!$slots.footer">
      <ModalFooter v-bind="getMergeProps" @ok="okEvent" @cancel="cancelEvent">
        <template #[item]="data" v-for="item in Object.keys($slots)">
          <slot :name="item" v-bind="data || {}"></slot>
        </template>
      </ModalFooter>
    </template>

    <template #default>
      <slot></slot>
    </template>

    <template #[item]="data" v-for="item in Object.keys(omit($slots, 'default'))">
      <slot :name="item" v-bind="data || {}"></slot>
    </template>
  </vxe-modal>
</template>
<script lang="ts" setup>
  import { computed, ref, watch, unref, watchEffect, useAttrs, getCurrentInstance } from 'vue';
  import { VxeModal, VxeModalInstance, ModalVisibleParams, VxeModalDefines } from 'vxe-table';

  import { ModalProps, ModalMethods, VxeModalPropNames, ModalPropNames } from './typing';

  import ModalFooter from './components/ModalFooter.vue';
  import ModalHeader from './components/ModalHeader.vue';
  import { isFunction } from '@/utils/is';
  // import { buildShortUUID } from '@/utils/uuid';
  import { deepMerge } from '@/utils';
  import { modalProps } from './props';
  import { omit, pick } from 'lodash-es';

  defineOptions({ name: 'AdVxeModal' });

  const props = defineProps(modalProps);
  const emit = defineEmits([
    'register',
    'open-change',
    'update:open',
    'show',
    'hide',
    'confirm',
    'cancel',
    'close',
    'zoom',
    'ok',
  ]);
  const attrs = useAttrs();
  const modalRef = ref<VxeModalInstance>();
  const openRef = ref(false);
  const propsRef = ref<Partial<ModalProps> | null>(null);

  const getMergeProps = computed((): ModalProps => {
    const mergeProps = {
      ...props,
      ...unref(propsRef),
    };
    return mergeProps;
  });

  const getProps = computed((): ModalProps => {
    const opt = {
      ...unref(getMergeProps),
      // open: unref(openRef),
      cancelButtonProps: undefined,
      okButtonProps: undefined,
      title: undefined,
    };
    return {
      ...opt,
    };
  });

  const getBindValue = computed((): ModalProps => {
    const attr = {
      ...attrs,
      ...unref(getMergeProps),
      // open: unref(openRef),
    };
    return pick(attr, VxeModalPropNames);
  });

  // 弹窗对象
  const getModal = computed(() => unref(modalRef));

  const modalMethods: ModalMethods = {
    getModal: () => unref(getModal),
    isOpen: () => unref(openRef),
    setModalProps,
  };

  /**
   * @description: 设置modal参数
   */
  function setModalProps(props: Partial<ModalProps>): void {
    // Keep the last setModalProps
    const propsTmp = pick(props, [...VxeModalPropNames, ...ModalPropNames]);
    propsRef.value = deepMerge(unref(propsRef) || ({} as any), propsTmp);
    if (Reflect.has(props, 'open')) {
      openRef.value = !!props.open;
    }
  }

  const instance = getCurrentInstance();
  if (instance) {
    emit('register', modalMethods, instance.uid);
  }

  watchEffect(() => {
    openRef.value = !!props.open;
  });

  watch(
    () => unref(openRef),
    (v) => {
      emit('open-change', v);
      emit('update:open', v);
    },
    {
      immediate: false,
    },
  );

  /** 弹窗标题双击事件 */
  async function titleDbClickEvent() {
    // if (props.showZoom) {
    //   await getModal.value?.zoom();
    // }
  }

  /** 在窗口隐藏之前执行，可以返回 Error 阻止关闭，支持异步。点击关闭，或者按 ESC 键之前可以拦截。 */
  async function beforeHideFn(params: ModalVisibleParams) {
    if (props.closeFunc && isFunction(props.closeFunc)) {
      const isClose: boolean = await props.closeFunc(params);
      // openRef.value = !isClose;
      // return;
      if (!isClose) {
        return new Error();
      }
    }
  }

  /** 在窗口显示时会触发该事件 */
  async function showEvent(e: VxeModalDefines.ShowEventParams) {
    emit('show', e);
  }
  /** 在窗口隐藏时会触发该事件 */
  async function hideEvent(e: VxeModalDefines.HideEventParams) {
    emit('hide', e);
  }
  /** 点击确定按钮时会触发该事件 */
  async function confirmEvent(e: VxeModalDefines.ConfirmEventParams) {
    emit('confirm', e);
  }
  /** 取消事件 */
  async function cancelEvent(e: Recordable) {
    openRef.value = false;
    emit('cancel', e);
  }
  /** 点击关闭按钮时会触发该事件 */
  async function closeEvent(e: VxeModalDefines.CloseEventParams) {
    emit('close', e);
  }
  /** 窗口缩放时会触发该事件 */
  async function zoomEvent(e: VxeModalDefines.ZoomEventParams) {
    emit('zoom', e);
  }
  /** 确认事件 */
  function okEvent(e: Recordable) {
    // openRef.value = false;
    emit('ok', e);
  }
</script>

<style lang="less">
  // .vxe-modal--wrapper .vxe-modal--content {
  //   padding: 0;
  // }
</style>
